package cn.anoxia.springframework.context.annotation;

import cn.anoxia.springframework.beans.factory.BeanDefinition;
import cn.anoxia.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import cn.anoxia.springframework.beans.support.BeanDefinitionRegistry;
import cn.hutool.core.util.StrUtil;

import java.util.Set;

/**
 * The class ClassPathBeanDefinitionScanner.
 * <p>
 * Description:
 *
 * @author: huangle
 * @since: 2021/08/31 14:53
 */
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {

  private BeanDefinitionRegistry registry;

  public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry){
    this.registry = registry;
  }

  public void doScan(String... basePackages){
    for(String basePackage:basePackages){
      Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
      for (BeanDefinition beanDefinition : candidates){
        // 解析 Bean 的作用域 singleton、prototype
        String scope = resolveBeanScope(beanDefinition);
        if (StrUtil.isNotBlank(scope)){
          beanDefinition.setScope(scope);
        }
        registry.registerBeanDefinition(determineBeanName(beanDefinition),beanDefinition);
      }
    }
    // 在设置 Bean 属性之前，允许 BeanPostProcessor 修改属性值
    registry.registerBeanDefinition("cn.anoxia.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor",
            new BeanDefinition(AutowiredAnnotationBeanPostProcessor.class));
  }

  /**
   * @Description: 获取scope注解的值
   * @author huangle
   * @Date 2021/8/31-15:03
   * @param beanDefinition
    * @return: java.lang.String
   */
  private String resolveBeanScope(BeanDefinition beanDefinition){
    Class<?> beanClass = beanDefinition.getBeanClass();
    Scope annotation = beanClass.getAnnotation(Scope.class);
    if (null!=annotation){
      return annotation.value();
    }
    return StrUtil.EMPTY;

  }

  /**
   * @Description: 获取Component注解的值
   * @author huangle
   * @Date 2021/8/31-15:03
   * @param beanDefinition
    * @return: java.lang.String
   */
  private String determineBeanName(BeanDefinition beanDefinition){
    Class<?> beanClass = beanDefinition.getBeanClass();
    Component annotation = beanClass.getAnnotation(Component.class);
    String value = annotation.value();
    if (StrUtil.isNotBlank(value)){
      value = StrUtil.lowerFirst(beanClass.getSimpleName());
    }
    return value;
  }

}
